import {
  ButtonContainerState,
  calcDynaClass,
  calcLayoutHeightWidth,
  ControlVO,
  IDashboardController,
  IPortletContainerController,
  IPortletController,
  UIActionButtonState,
  UIActionUtil,
} from '@ibiz-template/runtime';
import { IDBPortletPart, IUIActionGroupDetail } from '@ibiz/model-core';
import { useNamespace } from '@ibiz-template/vue3-util';
import { PortletPartState } from './portlet-part.state';

/**
 * 门户部件控制器基类
 *
 * @author lxm
 * @date 2022-10-20 20:10:25
 * @export
 * @class PortletPartController
 * @template T
 */
export class PortletPartController<T extends IDBPortletPart = IDBPortletPart>
  implements IPortletController
{
  readonly model: T;

  /**
   * 门户部件状态
   *
   * @type {PortletPartState}
   * @memberof PortletPartController
   */
  state: PortletPartState;

  /**
   * 数据看板控制器
   *
   * @author lxm
   * @date 2022-10-21 03:10:04
   * @type {IDashboardController}
   */
  readonly dashboard: IDashboardController;

  /**
   * 父容器控制器，最上级的没有
   *
   * @author lxm
   * @date 2022-10-21 03:10:05
   * @type {ContainerPortletController}
   */
  readonly parent?: IPortletContainerController;

  /**
   * 门户部件的上下文参数
   *
   * @author lxm
   * @date 2022-10-23 16:10:50
   * @readonly
   * @type {IContext}
   */
  get context(): IContext {
    return this.dashboard.context;
  }

  /**
   * 门户部件的视图参数
   *
   * @author lxm
   * @date 2022-10-23 16:10:21
   * @readonly
   * @type {IParams}
   */
  get params(): IParams {
    return this.dashboard.params;
  }

  /**
   * 获取容器类名集合
   * @author lxm
   * @date 2023-08-02 06:06:12
   * @readonly
   * @type {string[]}
   */
  get containerClass(): string[] {
    return [...this.state.class.container, ...this.state.class.containerDyna];
  }

  /**
   * Creates an instance of PortletPartController.
   * @author lxm
   * @date 2022-10-21 10:10:44
   * @param {T} model
   * @param {DashboardController} dashboard 数据看板控制器
   * @param {IPortletContainerController} [parent] 父容器控制器，最上级不存在
   */
  constructor(
    model: T,
    dashboard: IDashboardController,
    parent?: IPortletContainerController,
  ) {
    this.model = model;
    this.dashboard = dashboard;
    this.parent = parent;
    this.state = this.createState();
  }

  /**
   * 子类不可覆盖或重写此方法，在 init 时需要重写的使用 onInit 方法。
   *
   * @author lxm
   * @date 2022-08-18 22:08:30
   * @returns {*}  {Promise<void>}
   */
  async init(): Promise<void> {
    await this.onInit();
  }

  protected async onInit(): Promise<void> {
    // 初始化布局参数
    const { layoutPos, portletType, sysCss } = this.model;

    // 初始化高宽
    if (layoutPos) {
      const { width, height } = calcLayoutHeightWidth(this.model);
      this.state.layout.width = `${width}`;
      this.state.layout.height = `${height}`;
    }

    // 给col添加各自类型的类名
    const ns = useNamespace('portlet-col');
    this.state.layout.extraClass.push(ns.m(portletType!.toLowerCase()));

    if (sysCss?.cssName) {
      this.state.class.container.push(sysCss.cssName);
    }

    await this.initActionStates();
  }

  /**
   * 创建门户控件的状态对象
   *
   * @protected
   * @returns {*}  {PortletPartState}
   * @memberof PortletPartController
   */
  protected createState(): PortletPartState {
    return new PortletPartState();
  }

  /**
   * 初始化标题右侧界面行为按钮的状态
   *
   * @author chitanda
   * @date 2023-08-02 17:08:04
   * @return {*}  {Promise<void>}
   */
  async initActionStates(): Promise<void> {
    // 操作列按钮状态控制
    const { uiactionGroup } = this.model;
    if (!uiactionGroup?.uiactionGroupDetails?.length) {
      return;
    }
    const containerState = new ButtonContainerState();
    uiactionGroup.uiactionGroupDetails.forEach(detail => {
      const actionid = detail.uiactionId;
      if (actionid) {
        const buttonState = new UIActionButtonState(
          detail.id!,
          this.dashboard.context.srfappid!,
          actionid,
        );
        containerState.addState(detail.id!, buttonState);
      }
    });
    await containerState.update();
    this.state.actionGroupState = containerState;

    // 实体门户视图监听视图数据变更，刷新界面行为组的状态。
    const { appDataEntityId } = this.dashboard.view.model;
    if (appDataEntityId) {
      this.dashboard.view.evt.on('onDataChange', event => {
        let data = event.data[0];
        if (data && data instanceof ControlVO) {
          data = data.getOrigin();
        }
        if (data) {
          this.state.actionGroupState!.update(data, appDataEntityId);
        }
      });
    }
  }

  /**
   * 触发操作列点击事件
   *
   * @author lxm
   * @date 2022-09-07 22:09:46
   * @param {IPSUIActionGroupDetail} detail
   * @param {MouseEvent} event
   */
  async onActionClick(
    detail: IUIActionGroupDetail,
    event: MouseEvent,
    data: IData[] = [],
  ): Promise<void> {
    const actionId = detail.uiactionId;

    await UIActionUtil.execAndResolved(actionId!, {
      context: this.dashboard.context,
      params: this.dashboard.params,
      data,
      view: this.dashboard.view,
      event,
    });
  }

  /**
   * 表单数据变更通知(由表单控制器调用)
   *
   * @author lxm
   * @date 2022-09-20 18:09:56
   * @param {string[]} names
   */
  async dataChangeNotify(data: IData): Promise<void> {
    // 计算界面行为组状态
    if (this.state.actionGroupState) {
      const { appDataEntityId } = this.dashboard.view.model;
      this.state.actionGroupState.update(data, appDataEntityId);
    }

    // 计算动态样式表
    this.calcDynaClass(data);
  }

  /**
   * 计算动态样式表
   * @author lxm
   * @date 2023-08-02 06:15:08
   * @param {IData} data
   */
  protected calcDynaClass(data: IData): void {
    if (this.model.dynaClass) {
      const dynaClass = calcDynaClass(this.model.dynaClass, data);
      if (dynaClass.length) {
        this.state.class.containerDyna = dynaClass;
      }
    }
  }
}
